/*
 *  Matrix3.h
 *  RTDemo
 *
 *  Created by steveca  on 28/04/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef __MATRIX3X3_H__
#define __MATRIX3X3_H__

#include "Vector3.h"

namespace RTRT 
{
    class Matrix3
        {
        public:
            inline Matrix3()
            {}
            
            inline explicit Matrix3(const float arr[3][3])
            {
                memcpy(m,arr,9 * sizeof(float) );
            }
            
            inline Matrix3(const Matrix3& _matrix)
            {
                memcpy(m,_matrix.m,9 * sizeof(float) );
            }
            
            Matrix3 (Real fEntry00, Real fEntry01, Real fEntry02,
                     Real fEntry10, Real fEntry11, Real fEntry12,
                     Real fEntry20, Real fEntry21, Real fEntry22)
            {
                m[0][0] = fEntry00;
                m[0][1] = fEntry01;
                m[0][2] = fEntry02;
                m[1][0] = fEntry10;
                m[1][1] = fEntry11;
                m[1][2] = fEntry12;
                m[2][0] = fEntry20;
                m[2][1] = fEntry21;
                m[2][2] = fEntry22;
            }
            
            inline float *operator [] (size_t row) const
            {
                return (float*) m[row];
            }
            
            inline Matrix3& operator = (const Matrix3& _matrix)
            {
                memcpy(m, _matrix.m, 9 * sizeof(float) );
                return *this;
            }
            
        
            
            Vector3 getColumn(size_t column) const;
            void setColumn(const size_t column, const Vector3& vec);
            bool operator == (const Matrix3& _matrix) const;
            inline bool operator != (const Matrix3& _matrix) const 
            {
                // explicitly call operator ==
                return !operator==(_matrix)
            }
            
            // arithmetic operations
            Matrix3 operator + (const Matrix3& _matrix) const;
            Matrix3 operator - (const Matrix3& _matrix) const; 
            Matrix3 operator * (const Matrix3& _matrix) const;
            Matrix3 operator - () const;
            
            // Matrix * Vector operator [3X3 * 3X1 = 3X1]
            Vector3 operator * (const Vector3& _vector) const;
            
            // Vector * Matrix [1X3 * 3X3 = 1X3]
            friend Vector3 operator * (const Vector3& _vector, const Matrix3& _matrix);
            
            // Matrix * Scaler
            Matrix3 operator * (const float scaler) const;
            
            // Scaler * Matrix
            friend Matrix3 operator * (float scaler, const Matrix3& _matrix);
            
            // Utilities
            Matrix3 transpose() const;
            bool inverse(Matrix3& _matrix, float tolerance = 1e-06) const;
            Matrix3 inverse(float tolerance = 1e-06) const;
            float determinant() const;
            
            // Singular Value Decomposition
            // TODO:
                        
            static const float EPSILON;
            static const Matrix3 ZERO;
            static const Matrix3 IDENTITY;
            
        protected:

            float m[3][3];
            
        
        };
}


#endif